Import mojo
Import diddy
Import model

Class BonusBubbleBurstScreen Extends Screen
	Field spark:GameImage
	Field glow1:GameImage
	Field ballonList:ArrayList<BallonSprite> = New ArrayList<BallonSprite>
	Field starsList:ArrayList<StarSprite> = New ArrayList<StarSprite>
	Field maxBubbles:Int = 5
	Field maxStars:Int = 5
	Field currentStar:Int=0
	Field burstCount:Int = 0
	Field totalCount:Int = 5
	Field oddevens:Int = 0 ' 0=evens, 1=odd 
	Field starsCollected:Int = 0
	Field bonusGameOver:Bool = false
	Field scoreStatusBar:ScoreStatusBar
	Field timer:Int = 10000
Field BALLRAY = 36                   ' All balls are of the same ray / mass
Field NBALLS = 15                    ' N. of balls. MUST BE AT LEAST 3
Field BALLQRAY
Field BALLQRAYDST

	Method New()

		name = "Game"


		BALLQRAY = BALLRAY * BALLRAY
     	BALLQRAYDST = BALLQRAY * 4 * 1.1
Print "BALLQRAYDST: "+BALLQRAYDST
		spark = game.images.Find("spark")
		glow1 = game.images.Find("glow-1")
		scoreStatusBar = New ScoreStatusBar(SCREEN_WIDTH-20, SCREEN_HEIGHT-20)

		For local ndx:Int=0 = 1 to maxBubbles
			local newBallon:BallonSprite = New BallonSprite(ndx)
	
			ballonList.Add(newBallon)
		Next

		For local ndx:Int=0 = 1 to maxStars
			local newBallon:StarSprite = New StarSprite()
			starsList.Add(newBallon)
		Next

		GenerateBallons()
		
	End
	
	Method Start:Void()
				
		game.screenFade.Start(50, false)
			if(oddevens=0)
			_model.messageWindow.Show("BURST EVEN BALLONS!!")
		Else
			_model.messageWindow.Show("BURST ODD BALLONS!!")
		Endif

		bonusGameOver=false
		SetUpdateRate 60
	End
	
	Method Render:Void()
		Cls	50,50,255
		
		For Local ndx:Int=0 Until ballonList.Size
			Local val:BallonSprite = ballonList.Get(ndx)
			val.Draw
		Next
		
		For Local ndx:Int=0 Until starsList.Size
			Local val:StarSprite = starsList.Get(ndx)
			val.Draw()
		Next
		
		Particle.DrawAll()
		FPSCounter.Draw(0,0)
		DrawText(timer, SCREEN_WIDTH-50, 50)
		_model.statusPanel.Draw()
		_model.messageWindow.Draw()
		scoreStatusBar.Draw()
		
		DrawText qdist ( ballonList.Get(0).x,  ballonList.Get(0).y,  ballonList.Get(1).x,  ballonList.Get(1).y ), 0,200
	End
	
	Method Update:Void()
		timer-=1

if(timer<0)
Endif
		if(_model.messageWindow.visible=false and bonusGameOver=false)
		If TouchHit()
			For Local ndx:Int=0 Until starsList.Size
				Local starSprite:StarSprite = starsList.Get(ndx)
				If(starSprite.MouseCollide(game.mouseX, game.mouseY))
					starSprite.visible=false
					_model.addStar()
					starsCollected += 1
					For Local i% = 1 To 3
						Particle.Create(glow1, game.mouseX , game.mouseY, Rnd(-2,2), Rnd(-3,-1), GRAVITY/4, 2000)
					Next
				Endif
			Next
		Endif
		
		' collision checks
		For Local ndx:Int=0 Until ballonList.Size
			Local val:BallonSprite = ballonList.Get(ndx)
				if ( val.visible=false)
					continue
				Endif

			For Local ndx2:Int=ndx+1 Until ballonList.Size								
				Local val2:BallonSprite = ballonList.Get(ndx2)				
				if (bounce ( val, val2 ))
					Print "BOUNCE!!"
			 	End
			 Next
		Next

		For Local ndx:Int=0 Until ballonList.Size
				Local val:BallonSprite = ballonList.Get(ndx)

				val.Update

				If TouchHit()
					If(val.MouseCollide(game.mouseX, game.mouseY) and val.visible)
						val.visible=false
						For Local i% = 1 To 3
							Particle.Create(spark, game.mouseX , game.mouseY, Rnd(-2,2), Rnd(-3,-1), GRAVITY/4, 2000)
						Next
						
						
						
						if(val.number Mod 2=oddevens)	
							
						#rem						
							burstCount+=1	
							Local starSprite:StarSprite= starsList.Get(currentStar)				
								starSprite.x=val.x
								starSprite.y=val.y
								starSprite.visible=true		
								currentStar+=1
								if(currentStar=maxStars)
									currentStar=0
								Endif	
						#end
					
						totalCount-=1
						scoreStatusBar.value+=1
						Print "totalCount decremented:"+totalCount
						Else
scoreStatusBar.value-=1
							
						Endif
						
						'GenerateBallon(val)
						
						Continue 
					End
				End
							
				
		Next
		
	
		For Local ndx:Int=0 Until starsList.Size
			Local val:StarSprite = starsList.Get(ndx)
			val.Update()
		Next
		
		Particle.UpdateAll()
		
		if(totalCount=0)
			GenerateBallons()
		Endif
		End
	
		_model.messageWindow.Update()
	
	End
	
	Method onFinish:void()
		_model.messageWindow.Show("YOU GOT "+starsCollected+ " STARS!", new EndGameMessageCallback())
		bonusGameOver=true
	End

	Method PostFadeOut:Void()
		Particle.Clear()
		Super.PostFadeOut()
	End

	Method GenerateBallons:void()
		totalCount=0
			For Local ndx:Int=0 Until ballonList.Size
			Local val:BallonSprite = ballonList.Get(ndx)
			GenerateBallon(val)

			if(val.number Mod 2=oddevens)	
				totalCount+=1
			Endif
		Next
	Print "totalCount= "+totalCount
	End

	Method GenerateBallon(sprite:BallonSprite)
		sprite.Generate()
		
		if(ballonList.Size=0)
			return
		Endif
		
		For Local ndx:Int=0 Until ballonList.Size
			Local val:BallonSprite = ballonList.Get(ndx)
			if(sprite.id<>val.id)
			if (sprite.Collide(val))
				GenerateBallon(sprite)
				return
			Endif
			Endif
		Next

	End


 'Balls collisions, checking and handling
 '
 '************************************************************************
''

Method bounce:Bool( ball1:BallonSprite, ball2:BallonSprite )  
#rem
	// The following checkings based on ball.bouncedBy 
	// avoids the "I-bounced-you-you-bounced-me" syndrome. Anyway:
	// 1) You must have at least 3 balls (not too few), since
	// otherwise successive crashes between the same balls won't be tracked
	// 2) You can't have neither too much balls, nor a window too small, 
	// because the stuff works well when there aren't groups of attached 
	// balls
	//
#end

	Local d:Float = qdist ( ball1.x, ball1.y, ball2.x, ball2.y )
	
	if ( d >= BALLQRAYDST )
		'Print "1"
		return false
	endif

	if ( ball1.bouncedBy = ball2.id )
	'	Print "2"
		return false
	endif

	'  sOrt is the Center1 -> Center2 vector
	' sPar is its orthogonal, with right-hand rule orientation 

	Local sPar:TVector = new TVector ( ball2.x - ball1.x, ball2.y - ball1.y )
	Local sOrt:TVector = new TVector ( ball1.y - ball2.y, ball2.x - ball1.x )

   
	' Calculates components of the vector ortogonal to the Center1->Center2
	' vector

	Local sParMod:Float = sPar.mod2

	Local cosTh:Float = sPar.vx / sParMod
	Local sinTh:Float = sPar.vy / sParMod


	#rem
	   Calculates the components of velocities along sPar and sOrt
	#end
  
	Local vc1:TVector = new TVector ( ball1.dx * cosTh + ball1.dy * sinTh, 
							ball1.dy * cosTh - ball1.dx * sinTh )

	Local vc2:TVector = new TVector ( ball2.dx * cosTh + ball2.dy * sinTh,
							ball2.dy * cosTh - ball2.dx * sinTh )


	#rem
	 Checks for signs to see if we're effectively crashing together
	#end

	if ( (vc1.vx < 0 and vc2.vx > 0) or ( vc1.vx<=0 and vc2.vx<=0) )
	'	Print "3"
		return false
	endif

	#rem
	  Calculates new components, case of same masses
	#end

	Local vc1n:TVector = New TVector(vc2.vx, vc1.vy)	 
	Local vc2n:TVector = New TVector(vc1.vx, vc2.vy)

	'vc1n.vx = vc2.vx
	'vc2n.vx = vc1.vx


	' Brings back the new speed values into xy system
	'
	ball1.dx = vc1n.vx * cosTh - vc1n.vy * sinTh
	ball1.dy = vc1n.vx * sinTh + vc1n.vy * cosTh

	ball2.dx = vc2n.vx * cosTh - vc2n.vy * sinTh
	ball2.dy = vc2n.vx * sinTh + vc2n.vy * cosTh
		
	Print ball1.id +" collided with "+ball2.id+ ",dx="+ball1.dx+"dy="+ball1.dy
	Print ball2.id +" collided with "+ball1.id+ ",dx="+ball2.dx+"dy="+ball2.dy
	' Registers bouncing
	'
	ball1.bouncedBy = ball2.id
	ball2.bouncedBy = ball1.id
ball1.number+=1
ball2.number+=1
	return true

End

' Squared distance
'
Method qdist:Float(x1:Float, y1:Float, x2:Float, y2:Float)
	Local dx:Float = x2 - x1
	Local dy:Float = y2 - y1
	return dx * dx + dy * dy

End
End 'class

Class TVector
	Field vx:Float
	Field vy:Float
	Field mod2:Float
	Field qMod:Float

	Method New(vx:Int, vy:int)
		self.vx = vx
		self.vy = vy
		self.mod2 = VectMod()
		self.qMod = VectQMod()
	End


	' Module and squared module (both are calculated directly, without
	' ^ operator, nor inter-function calling, because of speed reasons)
	'

	Method VectMod () ' CLASS METHOD - DO NOT USE DIRECTLY
		return Sqrt ( vx * vx + vy * vy )
	End

	Method VectQMod ()    ' CLASS METHOD - DO NOT USE DIRECTLY
		return vx * vx + vy * vy
	End

End 'class TVector

Class EndGameMessageCallback Implements WindowCallback

	Method onClose:Void()
		_model.bonusGameSuccess=true
		_model.bonusGameFailed=false
		game.screenFade.Start(50, True)
		game.nextScreen = _model._mazeScreen
	End
End

Class StarSprite Extends Sprite
	
	Method New()
		Super.New(game.images.Find("collectStar"), 0, 0)			
		visible=false	
			
		speed=-1	
	End
		
	
	Method Update()

		If (y>SCREEN_HEIGHT)
			visible=false
		End
		If (visible)
			MoveForward()
		Else
			x=-50
		Endif
	End
	
	Method Draw:Void()
		If (visible)
			Super.Draw(0,0)
		End
	End
	
	Method MouseCollide:Int(xhit:Int, yhit:Int)
		Return RectsOverlap(x + hitBoxX, y + hitBoxY, hitBoxWidth, hitBoxHeight, xhit-5 , yhit-5,  10, 10)
	End
		
End

Class BallonSprite Extends Sprite
	Field number
	Field numberMax=50
	Field id:Int
	Field collided:Bool = false
	Field bouncedBy:Int = -1

	Method New(id:Int)
		Super.New(game.images.Find("ballon1")	, 0, 0)	
		self.id	= id				
	End
		
	Method Generate:Void()
		x=Rnd(SCREEN_WIDTH)
		y=Rnd(SCREEN_HEIGHT)

		dy=(Rnd(10))
		dx=(Rnd(10))
		speed=2
		self.number=0'Rnd(1,numberMax)
		collided=false
		visible=true
		Print "---"
		Print number
		Print dx
		Print dy
		Print "---"
	End
	
	Method Update()
		Local retval:Bool = false

		
		If(x-image.w2<0)
			x=image.w2
			dx=-dx
			retval = true
		ElseIf(x+image.w2>SCREEN_WIDTH)
			x=SCREEN_WIDTH-image.w2
			dx=-dx
			retval = true
		Endif
		If(y-image.h2<0)
			y=image.w2
			dy=-dy
			retval = true
		ElseIf(y+image.h2>SCREEN_HEIGHT)
			y=SCREEN_HEIGHT-image.h2
			dy=-dy
			retval = true
		Endif
		
		if(retval)
			bouncedBy = -1
		endif

		'If(collided)
			' Needs improving. Too tired after a looong week....
		''	dx=-dx
		''	dy=-dy
		''	collided=false
		'Endif
		Move()
	End
	
	Method Draw:Void()
		if(visible)
			Super.Draw(0,0)
			_model.font.DrawText(id, x, y-5, AngelFont.ALIGN_CENTER)
		EndIf
	End
	
	Method MouseCollide:Int(xhit:Int, yhit:Int)
		Return RectsOverlap(x + hitBoxX, y + hitBoxY, hitBoxWidth, hitBoxHeight, xhit , yhit, 2, 2)
	End
		
End

Class ScoreStatusBar
Field value:Int = 0
Field x:Int = 0
Field y:Int = 0

Method New(x:Int, y:Int)
		self.x = x
		self.y=y			
	End

Method Draw:Void()
	SetColor(255,0,0)
	DrawRect(x,y-(value*50), x+10, y)
	SetColor(255,255,255)
End
End


